﻿namespace com.oakwoodsys.Extensions.SharePointExtensions
{
    using System;
    using System.Globalization;
    using System.Linq;

    using com.oakwoodsys.Exceptions.SharePointExceptions;

    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Administration;

    public static class SPSiteExtensions
    {
        #region Methods

        public static void ActivateFeature( this SPSite spSite, Guid featureId )
        {
            SPFeatureDefinition f = SPFarm.Local.GetFeatureDefinition( featureId );
            if ( f == null )
                throw new FeatureNotFoundException( featureId );
            else
            {
                if ( f.Scope == SPFeatureScope.Site )
                {
                    try
                    {
                        SPFeature spFeature = spSite.Features.FirstOrDefault( a => a.DefinitionId.Equals( featureId ) );
                        if ( spFeature == null )
                        {
                            spSite.Features.Add( featureId );
                        }
                    }
                    catch ( Exception e )
                    {
                        throw new FeatureActivationException( featureId, f.GetTitle( CultureInfo.CurrentCulture ), spSite.Url, e );
                    }
                }
                else
                    throw new FeatureActivationFailedNotScopedForSiteException( featureId, f.GetTitle( CultureInfo.CurrentCulture ), spSite.Url );
            }
        }

        /// <summary>
        /// Adds a new group to the root web of the site collection. 
        /// Exceptions: SiteGroupAlreadyExistsException: Group by the specified name already exist.
        /// </summary>
        /// <param name="spSite"></param>
        /// <param name="groupName">Name of the new group</param>
        /// <param name="owner">Group owner</param>
        /// <param name="defaultUser">Default user</param>
        /// <param name="groupDescription">Description associated with the group</param>
        /// <returns>The created group as type SPGroup</returns>
        public static SPGroup AddSiteGroup( this SPSite spSite, string groupName, SPUser owner, SPUser defaultUser, string groupDescription )
        {
            SPWeb spWeb = spSite.RootWeb;
            {
                SPGroup spGroup = spWeb.Groups.Cast<SPGroup>( ).ToList( ).FirstOrDefault( a => a.Name.Equals( groupName ) );
                if ( spGroup != null )
                    throw new SiteGroupAlreadyExistsException( groupName );
                else
                {
                    try
                    {
                        spWeb.SiteGroups.Add( groupName, owner, defaultUser, groupDescription );
                        spWeb.Update( );
                        spGroup = spWeb.SiteGroups[ groupName ];
                        return spGroup;
                    }
                    catch
                    {
                        throw;
                    }
                }
            }
        }

        /// <summary>
        /// Adds a new group to the root web of the site collection. The owner and the default user of the group is the first administrator found within the site administrators group.
        /// Exceptions: NoSiteAdministratorFoundException: No site administrators found for the site.
        /// </summary>
        /// <param name="spSite"></param>
        /// <param name="groupName"></param>
        /// <param name="groupDescription"></param>
        /// <returns></returns>
        public static SPGroup AddSiteGroup( this SPSite spSite, string groupName, string groupDescription )
        {
            SPWeb spWeb = spSite.RootWeb;
            {
                if ( spWeb.SiteAdministrators.Count > 0 )
                {
                    SPUser spUser = spWeb.SiteAdministrators[ 0 ];
                    return spSite.AddSiteGroup( groupName, spUser, spUser, groupDescription );
                }
                else
                    throw new NoSiteAdministratorFoundException( );
            }
        }

        public static void DeactivateFeature( this SPSite spSite, Guid featureId )
        {
            SPFeatureDefinition f = SPFarm.Local.GetFeatureDefinition( featureId );
            if ( f == null )
                throw new FeatureNotFoundException( featureId );
            else
            {
                if ( f.Scope == SPFeatureScope.Site )
                {
                    try
                    {
                        SPFeature spFeature = spSite.Features.FirstOrDefault( a => a.DefinitionId.Equals( featureId ) );
                        if ( spFeature != null )
                            spSite.Features.Remove( featureId );
                    }
                    catch ( Exception e )
                    {
                        throw new FeatureDeactivationException( featureId, f.GetTitle( CultureInfo.CurrentCulture ), spSite.Url, e );
                    }
                }
                else
                    throw new FeatureDeactivationFailedNotScopedForSiteException( featureId, f.GetTitle( CultureInfo.CurrentCulture ), spSite.Url );
            }
        }

        public static SPGroup GetSiteGroup( this SPSite spSite, string groupName )
        {
            SPWeb spWeb = spSite.RootWeb;
            {
                SPGroup spGroup = spWeb.Groups.Cast<SPGroup>( ).ToList( ).FirstOrDefault( a => a.Name.Equals( groupName ) );
                return spGroup;
            }
        }

        public static bool IsFeatureActivated( this SPSite spSite, Guid featureId )
        {
            SPFeature spFeature = spSite.Features.FirstOrDefault( a => a.DefinitionId.Equals( featureId ) );
            return spFeature == null ? false : true;
        }

        public static bool IsFeatureScoped( this SPSite spSite, Guid featureId )
        {
            SPFeatureDefinition f = SPFarm.Local.GetFeatureDefinition( featureId );
            if ( f == null )
                return false;
            else
                return f.Scope == SPFeatureScope.Site;
        }

        public static bool SiteGroupExists( this SPSite spSite, string groupName )
        {
            SPWeb spWeb = spSite.RootWeb;
            {
                SPGroup spGroup = spWeb.Groups.Cast<SPGroup>( ).ToList( ).FirstOrDefault( a => a.Name.Equals( groupName ) );
                return spGroup == null ? false : true;
            }
        }

        #endregion Methods
    }
}